//和连接池相关的函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>

#include "configure.h"
#include "macro.h"
#include "global.h"
#include "function.h"
#include "mysocket.h"
#include "lock_mutex.h"
#include "mymemory.h"

connection_s::connection_s() {
	current_sequence = 0;
	pthread_mutex_init(&logic_proc_mutex, NULL);
}

connection_s::~connection_s() {
	pthread_mutex_destroy(&logic_proc_mutex);

}

//从连接池中分配一个可用连接，并初始化
void connection_s::GetOneToUse() {
	++current_sequence;
	
	fd = -1;
	//初始化与收包、发包相关
	current_stat = _PKG_HD_INIT;
	recv_buf = data_head_info;
	recv_len = sizeof(COMM_PKG_HEADER);
	throw_send_count = 0;
	recv_mem_pointer = NULL;
	send_mem_pointer = NULL;
	events = 0;

	//心跳包相关
	last_ping_time = time(NULL);

	//flood相关
	flood_kick_last_time = 0;
	flood_attack_count = 0;
	send_count = 0;

}

//回收回连接池前的操作
void connection_s::PutOneToFree() {
	++current_sequence;//一直没弄懂，为什么分配和回收都是加
	if(recv_mem_pointer != NULL){
		MyMemory::GetInstance()->FreeMemory(recv_mem_pointer);
		recv_mem_pointer = NULL;
	}
	if(send_mem_pointer != NULL) {
		MyMemory::GetInstance()->FreeMemory(send_mem_pointer);
		send_mem_pointer = NULL;
	}
	throw_send_count = 0;
}
//初始化连接池:
void MySocket::InitConnection() {
	lpconnection_t connect;
	MyMemory *memory = MyMemory::GetInstance();

	int connect_pool_len = sizeof(connection_t);
	for(int i=0; i < worker_connections_; ++i) {//初始分配
		connect = (lpconnection_t)memory->AllocMemory(connect_pool_len, true);

		connect = new(connect) connection_t();
		connect->GetOneToUse();
		connection_list_.push_back(connect);
		free_connection_list_.push_back(connect);
	}
	free_connections_ = total_connections_ = connection_list_.size();
	return;
}

//回收连接池，释放内存
void MySocket::ClearConnection() {
	lpconnection_t connect;
	MyMemory *memory = MyMemory::GetInstance();

	while(!connection_list_.empty()) {
		connect = connection_list_.front();
		connection_list_.pop_front();
		connect->~connection_t();
		memory->FreeMemory(connect);
	}
}

//从连接池中获取一个空闲连接
lpconnection_t MySocket::GetConnection(int sock) {
	Lock lock(&connection_mutex_);
	if(!free_connection_list_.empty()) {
		lpconnection_t connect = free_connection_list_.front();
		free_connection_list_.pop_front();

		connect->GetOneToUse();
		--free_connections_;
		connect->fd = sock;
		return connect;
	}
	MyMemory *memory = MyMemory::GetInstance();
	lpconnection_t connect = (lpconnection_t)memory->AllocMemory(sizeof(connection_t), true);
	connect = new(connect)connection_t();
	connect->GetOneToUse();
	connection_list_.push_back(connect);
	++total_connections_;
	connect->fd = sock;
	return connect;
}

//归还连接到连接池
void MySocket::FreeConnection(lpconnection_t connect) {
	Lock lock(&connection_mutex_);
	connect->PutOneToFree();
	free_connection_list_.push_back(connect);
	++free_connections_;
	return;
}

//将要回收的连接放入队列中
void MySocket::InRecyConnectQueue(lpconnection_t connect) {
	std::list<lpconnection_t>::iterator pos;
	bool if_find = false;
	Lock lock(&recy_connect_queue_mutex_);
	
	for(pos = recy_connection_list_.begin(); pos!=recy_connection_list_.end(); ++pos) {
		if((*pos) == connect) {
			if_find = true;
			break;
		}
	}
	if(if_find == true) {
		return;
	}
	connect->in_recy_time = time(NULL);
	++connect->current_sequence;
	recy_connection_list_.push_back(connect);
	++totol_recy_connections_;
	--online_user_count_;
	return;
}

//处理延迟回收的线程
void *MySocket::ServerRecyConnectionThread(void *thread_data) {
	ThreadItem *thread = static_cast<ThreadItem*>(thread_data);
	MySocket *socket_obj = thread->this_;
	time_t current_time;
	int err;
	std::list<lpconnection_t>::iterator pos,pos_end;
	lpconnection_t connect;
	while(1) {
		usleep(200*1000);
		if(socket_obj->totol_recy_connections_ > 0) {
			current_time = time(NULL);
			err = pthread_mutex_lock(&socket_obj->recy_connect_queue_mutex_);
			if(err != 0) {
				LogStderr(err, "MySocket::ServerRecyConnectionThread()中pthread_mutex_lock()失败，返回错误码为%d!",err);
			}
lblRRTD:
			pos = socket_obj->recy_connection_list_.begin();
			pos_end = socket_obj->recy_connection_list_.end();
			for(;pos!=pos_end;++pos) {
				connect = (*pos);
				if(((connect->in_recy_time + socket_obj->recy_connection_wait_time_) > current_time)&&(stop_event == 0)) {
				//没有到释放的时间
				continue;
				}
				//到达释放的时间
				if(connect->throw_send_count > 0) {
					LogStderr(0, "MySocket::ServerRecyConnectionThread()中释放时间,发现connect.throw_send_count!=0");
				}
				--socket_obj->totol_recy_connections_;
				socket_obj->recy_connection_list_.erase(pos);
				socket_obj->FreeConnection(connect);
				goto lblRRTD;
			}
			err = pthread_mutex_unlock(&socket_obj->recy_connect_queue_mutex_);
			if(err !=0 ) {
				LogStderr(err, "MySocket::ServerRecyConnectionThread()pthread_mutex_unlock()失败,返回错误码%d!",err);
			}
		}

		if(stop_event == 1) {
			if(socket_obj->totol_recy_connections_ > 0) {
				err = pthread_mutex_lock(&socket_obj->recy_connect_queue_mutex_);
				if(err != 0) {
					LogStderr(err, "MySocket::ServerRecyConnectionThread()中pthread_mutex_lock()失败,返回错误码为%d!",err);
				}
lblRRTD2:
				pos = socket_obj->recy_connection_list_.begin();
				pos_end = socket_obj->recy_connection_list_.end();
				for(;pos!=pos_end;++pos) {
					connect = (*pos);
					--socket_obj->totol_recy_connections_;
					socket_obj->recy_connection_list_.erase(pos);
					socket_obj->FreeConnection(connect);

					goto lblRRTD2;
				}
				err = pthread_mutex_unlock(&socket_obj->recy_connect_queue_mutex_);
				if(err != 0) {
					LogStderr(err, "MySocket::ServerRecyConnectionThread()中pthread_mutex_unlock()失败,错误码为%d",err);
				}
			}
			break;
		}
	}
	return (void*)0;
}


//关闭连接池
void MySocket::CloseConnection(lpconnection_t connect) {
	FreeConnection(connect);
	if(connect->fd != -1) {
		close(connect->fd);
		connect->fd = -1;
	}
	return;
}
